using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Reflection;
using System.Data.Common;

using Pampa.Grid.Data;
using Pampa.Grid.Core.Filters.Exceptions;

using Pampa.CRUD.Core;

namespace Pampa.Grid.Core.Filters
{
    public class SimpleFilter : BasicFilter
    {
        private string field;
        private OperationType operation;
        private object lvalue;

        #region Constructors

        public SimpleFilter() : base()
        { 
        }

        public SimpleFilter(string field, OperationType operation, object value) : base()
        {
            this.Field = field;
            this.Operation = operation;
            this.Value = value;
        }

        #endregion

        #region Properties

        public string Field
        {
            get { return field; }
            set { field = value; }
        }

        public OperationType Operation
        {
            get { return operation; }
            set { operation = value; }
        }

        public object Value
        {
            get { return lvalue; }
            set { lvalue = value; }
        }

        public string OperationScript
        {
            get
            {
                switch (this.Operation)
                {
                    case OperationType.Grater:
                        return ">";
                    case OperationType.GraterEqual:
                        return ">=";
                    case OperationType.Less:
                        return "<";
                    case OperationType.LessEqual:
                        return "<=";
                    case OperationType.Equal:
                        return "=";
                    case OperationType.NotEqual:
                        return "<>";
                    case OperationType.StartsWith:
                    case OperationType.Contains:
                    case OperationType.EndsWith:
                        return "LIKE";
                    default:
                        return " unresolve ";
                }
            }
        }

        public object ValueScript
        {
            get
            {
                switch (this.Operation)
                {
                    case OperationType.StartsWith:
                        return this.Value.ToString() + "%";
                    case OperationType.Contains:
                        return "%" + this.Value.ToString() + "%";
                    case OperationType.EndsWith:
                        return "%" + this.Value.ToString();
                    default:
                        return this.Value;
                }
            }
        }

        #endregion

        #region Xml

        protected override void LoadXml(XmlNode node)
        {
            XmlDocument document = node.OwnerDocument;

            string strOperation;
            string typeValue;
            string strValue;

            if (node.Attributes["Field"] == null)
            {
                if (node.Attributes["field"] == null)
                    throw (new MissingFilterFieldException());
                this.Field = node.Attributes["field"].Value;

                if (node.Attributes["operation"] == null)
                    throw (new MissingFilterOperationException());
                strOperation = node.Attributes["operation"].Value;

                if (node.Attributes["typevalue"] == null)
                    throw (new MissingFilterTypeValueException());
                typeValue = node.Attributes["typevalue"].Value;

                if (node.Attributes["value"] == null)
                    throw (new MissingFilterValueException());
                strValue = node.Attributes["value"].Value;
            }
            else
            {
                this.Field = node.Attributes["Field"].Value;

                if (node.Attributes["Operation"] == null)
                    throw (new MissingFilterOperationException());
                strOperation = node.Attributes["Operation"].Value;

                if (node.Attributes["TypeValue"] == null)
                    throw (new MissingFilterTypeValueException());
                typeValue = node.Attributes["TypeValue"].Value;

                if (node.Attributes["Value"] == null)
                    throw (new MissingFilterValueException());
                strValue = node.Attributes["Value"].Value;
            }

            this.Operation = (OperationType)Enum.Parse(typeof(OperationType), strOperation);

            this.Value = GetValue(typeValue, strValue);

            // PARCHE para cotas superiores de fechas
            if( (this.Value is DateTime) && ( (this.Operation == OperationType.Less) || (this.Operation == OperationType.LessEqual) ) )
            {
                this.Value = ((DateTime)this.Value).Date.AddHours(23).AddMinutes(59);
            }
        }

        protected override void BuildNode(ref XmlNode node)
        {
            XmlDocument document = node.OwnerDocument;

            XmlAttribute attribute = document.CreateAttribute("Field");
            attribute.Value = this.Field;
            node.Attributes.Append(attribute);

            attribute = document.CreateAttribute("Operation");
            attribute.Value = Enum.GetName(typeof(OperationType), this.Operation);
            node.Attributes.Append(attribute);

            attribute = document.CreateAttribute("Value");

            // Aca se determina como se representa el valor del filtro en un Xml
            if (this.Value is IIdDescription)
                attribute.Value = ((IIdDescription)this.Value).Id;
            else if (this.Value is DateTime)
                attribute.Value = ((DateTime)this.Value).ToShortDateString();
            else
                attribute.Value = this.Value.ToString();

            node.Attributes.Append(attribute);

            attribute = document.CreateAttribute("TypeValue");
            attribute.Value = this.Value.GetType().AssemblyQualifiedName;
            node.Attributes.Append(attribute);
        }

        private object GetValue(string typeValue, string strValue)
        {
            return EntityManager.GetValueFromString(Type.GetType(typeValue), strValue);
        }

        #endregion
    }
}
